Skip to content

fix(webapp): harden RouteErrorDisplay against null error.data - #4423

Closed
Ayush7614 wants to merge 1 commit into
triggerdotdev:mainfrom
Ayush7614:fix/route-error-display-null-data
Closed

fix(webapp): harden RouteErrorDisplay against null error.data#4423
Ayush7614 wants to merge 1 commit into
triggerdotdev:mainfrom
Ayush7614:fix/route-error-display-null-data

Conversation

@Ayush7614

Copy link
Copy Markdown

Summary

RouteErrorDisplay read error.data.message without a null check. Remix route errors can have data: null, a string, or an empty object, which crashed the error boundary and blanked the page. Add getRouteErrorMessage with safe fallbacks + unit tests.

✅ Checklist

  • I have followed every step in the contributing guide
  • The PR title follows the convention.
  • I ran and tested the code works

Testing

  • Added apps/webapp/app/utils/httpErrors.test.ts covering null/undefined/string/{ message } cases
  • Verified RouteErrorDisplay uses getRouteErrorMessage instead of direct error.data.message access
  • Confirmed fallback messages still come from friendlyErrorDisplay when data is missing

Changelog

Dashboard error pages no longer crash when a route error has no data payload.

Remix route errors can have null/empty data; reading .message threw
inside the error boundary and blanked the page. Fall back safely.
@changeset-bot

changeset-bot Bot commented Jul 29, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 3e48edd

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions

Copy link
Copy Markdown
Contributor

Hi @Ayush7614, thanks for your interest in contributing!

This project requires that pull request authors are vouched, and you are not in the list of vouched users.

This PR will be closed automatically. See https://github.com/triggerdotdev/trigger.dev/blob/main/CONTRIBUTING.md for more details.

@github-actions github-actions Bot closed this Jul 29, 2026
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5af745a1-e765-4f44-8cac-6c907b1f8b89

📥 Commits

Reviewing files that changed from the base of the PR and between 2f1734c and 3e48edd.

📒 Files selected for processing (4)
  • .server-changes/fix-route-error-display-null-data.md
  • apps/webapp/app/components/ErrorDisplay.tsx
  • apps/webapp/app/utils/httpErrors.test.ts
  • apps/webapp/app/utils/httpErrors.ts

Walkthrough

Adds getRouteErrorMessage to safely derive messages from route error payloads, including string, object, null, and fallback cases. Updates RouteErrorDisplay to use the helper and adds Vitest coverage for these behaviors. Documents the fix in a server-changes record.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

Open in Devin Review

Comment on lines +9 to +32
it("falls back when data is null", () => {
expect(getRouteErrorMessage(500, "Internal Server Error", null)).toBe(
"Something went wrong on our end. Please try again later."
);
});

it("falls back when data is undefined", () => {
expect(getRouteErrorMessage(404, "Not Found", undefined)).toBe(
"The page you're looking for doesn't exist."
);
});

it("uses a string data body", () => {
expect(getRouteErrorMessage(400, "Bad Request", "Invalid payload")).toBe("Invalid payload");
});

it("falls back when message is missing or empty", () => {
expect(getRouteErrorMessage(403, "Forbidden", {})).toBe(
"You don't have permission to access this resource."
);
expect(getRouteErrorMessage(403, "Forbidden", { message: "" })).toBe(
"You don't have permission to access this resource."
);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 New error-message tests fail because fallback returns the status text, not the generic message

The fallback message is built from the shared helper (friendlyErrorDisplay(status, statusText).message at apps/webapp/app/utils/httpErrors.ts:50), which returns the provided status text whenever one is given rather than the generic default the new tests expect, so the added test suite fails.
Impact: The project's test run breaks, blocking the change from passing CI.

Mechanism: statusText short-circuits the default message

friendlyErrorDisplay returns statusText ?? <default> for every case (apps/webapp/app/utils/httpErrors.ts:5-43). Every new test passes a truthy statusText (e.g. "Internal Server Error", "Not Found", "Forbidden"), so friendlyErrorDisplay(...).message evaluates to that status text, never the generic default.

Concretely:

  • getRouteErrorMessage(500, "Internal Server Error", null) returns "Internal Server Error", but the test at apps/webapp/app/utils/httpErrors.test.ts:10-12 expects "Something went wrong on our end. Please try again later."
  • getRouteErrorMessage(404, "Not Found", undefined) returns "Not Found", but apps/webapp/app/utils/httpErrors.test.ts:16-18 expects "The page you're looking for doesn't exist."
  • getRouteErrorMessage(403, "Forbidden", {}) and (403, "Forbidden", { message: "" }) return "Forbidden", but apps/webapp/app/utils/httpErrors.test.ts:26-31 expects "You don't have permission to access this resource."

Either the implementation must resolve the generic default when data is missing (e.g. call friendlyErrorDisplay(status) without statusText), or the test expectations must be corrected to the status-text values.

Prompt for agents
The new tests in apps/webapp/app/utils/httpErrors.test.ts will fail because getRouteErrorMessage computes its fallback as friendlyErrorDisplay(status, statusText).message, and friendlyErrorDisplay returns `statusText ?? <default>` — so whenever a truthy statusText is supplied (as every test does), the fallback equals the status text, not the generic default the assertions expect. Decide the intended behavior: (1) if callers should see the friendly generic message when error.data is missing, change getRouteErrorMessage's fallback to friendlyErrorDisplay(status).message (omit statusText) so the default is used, and note this also changes RouteErrorDisplay's runtime output; or (2) if showing the status text is intended (matching the prior behavior of error.data.message ?? friendlyErrorDisplay(...).message), update the test expectations in httpErrors.test.ts to expect the passed statusText strings (e.g. 'Internal Server Error', 'Not Found', 'Forbidden'). Ensure the tests and implementation agree.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant